package com.song.client;

import com.song.Utils.SingletonFactory;
import com.song.transport.RPCResponse;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;

@Slf4j(topic = "c.NettyClientHandler")
public class NettyClientHandler extends SimpleChannelInboundHandler<RPCResponse> {

    private final UnprocessedRequests unprocessedRequests;

    public NettyClientHandler() {
        this.unprocessedRequests = SingletonFactory.getInstance(UnprocessedRequests.class);
    }

    /**
     * 处理用户获取到的读事件 第二个参数 是 Object msg   the message to handle
     * ChannelPipeline相当于流水线的传送带
     * ChannelHandler流水线上的每个步骤工人
     * ChannelHandlerContext就是待加工的产品
     * @param channelHandlerContext
     * @param rpcResponse
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RPCResponse rpcResponse) {
        //对读事件获取到的 RPCResponse进行处理
        //使用CompletableFuture异步计算通知 成功
        try {
            log.info(String.format("客户端接收到消息: %s", rpcResponse));
            //第三代
            unprocessedRequests.complete(rpcResponse);

//            CompletableFuture<RPCResponse> future = new CompletableFuture<>();//第二代
//            if(null != future) {
//                future.complete(rpcResponse);//返回CompletableFuture的异步计算结果，传给RPCClientProxy类的sendRequest发送rpcRequest时的CompletableFuture  get()获取
//            } else {
//                log.info("未收到服务端返回的RPCResponse数据：");
//                throw new RuntimeException();
//            }

//            AttributeKey<RPCResponse> key = AttributeKey.valueOf("rpcResponse");//第一代
//            channelHandlerContext.channel().attr(key).set(rpcResponse);
//            channelHandlerContext.channel().close();
        } finally {
            ReferenceCountUtil.release(rpcResponse);//ChannelInboundHandler负责显式地释放与池化ByteBuf实例相关的内存，Netty为此提供了一个实用方法ReferenceCountUtil.release()。
            //若不想处理释放资源，使用SimpleChannelInboundHandler自动释放资源，无需显示释放
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("过程调用时有错误发生:");
        cause.printStackTrace();
        ctx.close();
    }
}
